/*
			       ___ _      _   ___ _  _    ___  _  _ 
			      | __| |    /_\ / __| || |  / _ \| \| |
			      | _|| |__ / _ \\__ \ __ | | (_) | .` |
			      |_| |____/_/ \_\___/_||_|  \___/|_|\_|
			                                            
			  _____ _  _   _ _____   ___ ___ _____ ___ _  _ 
			 |_   _| || | /_\_   _| | _ )_ _|_   _/ __| || |
			   | | | __ |/ _ \| |   | _ \| |  | || (__| __ |
			   |_| |_||_/_/ \_\_|   |___/___| |_| \___|_||_|
			        F L A S H  O N  T H A T  B I T C H
			        
		+--------------------------------------------------------+
		|	This file is delivered as is. Any modifications to   |
		|   this class and/or sub classes may cause errors and   |
		|   can cause you compilations to fail. FOTB takes no	 |
		|   responsibility for any complications caused by the	 |
		|   following code or any modified versions of it.		 |
		+--------------------------------------------------------+

*/

package com.flashonthatbitch.filesystem.parsers {

/*
		 ___ __  __ ___  ___  ___ _____ 
		|_ _|  \/  | _ \/ _ \| _ \_   _|
		 | || |\/| |  _/ (_) |   / | |  
		|___|_|  |_|_|  \___/|_|_\ |_|  
		I M P O R T
*/
	import com.flashonthatbitch.filesystem.FileObject;
	import flash.utils.ByteArray;
	
	import flash.display.BitmapData;
	import flash.utils.Endian;

	public class ICO extends ParserPrototype {
		
		protected static const AND_ENCODING	:uint		= 0x01;		// 1
		protected static const XOR_ENCODING	:uint		= 0x04;		// 4
		protected static const XOR2_ENCODING	:uint		= 0x08;		// 8
		protected static const RGB_ENCODING	:uint		= 0x18;		// 24
		protected static const ARGB_ENCODING	:uint		= 0x20;		// 32
		
		protected static const TYPE_ICO		:uint		= 0x01;
		protected static const TYPE_CUR		:uint		= 0x02;
		protected static const RESERVED		:uint		= 0x00;
		
		protected var type					:uint		= 0;
		protected var numIconsInFile		:uint 		= 0;
		protected var iconEntries			:Array;
		
/*
		  ___ ___  _  _ ___ _____ ___ _   _  ___ _____ ___  ___ 
		 / __/ _ \| \| / __|_   _| _ \ | | |/ __|_   _/ _ \| _ \
		| (_| (_) | .` \__ \ | | |   / |_| | (__  | || (_) |   /
		 \___\___/|_|\_|___/ |_| |_|_\\___/ \___| |_| \___/|_|_\
		C O N S T R U C T O R
*/
			
		public function ICO(fileObject:FileObject=null) {
			
			super(fileObject);
			
		}
		
		override protected function parse():void {
			
			//set endian
			bytearray.endian = Endian.LITTLE_ENDIAN;
			
			//initial reserved (ignored)
			uint16;
			
			//type
			type = uint16;
			if(type!=TYPE_ICO)	//type validation
				throw getError("File is not a valid .ico file. type mismatch, found '"+type+"' instead of '"+TYPE_ICO+"'.");
			
			trace("type: " + type);
			
			// number of icon entries
			numIconsInFile = uint16;
			if(numIconsInFile<1) // check if it's empty
				throw getError("The ICO reads '0' icons and is therefore considered empty.");
			
			trace("numIconsInFile: " + numIconsInFile);
			
			iconEntries 	= new Array(numIconsInFile);
			var entry:IconEntry;
			
			var startPos:uint = bytearray.position;
			
			for(var i:uint=0;i<numIconsInFile*16;i+=16){
				entry 					= new IconEntry();
				entry.width 			= uint8;
				entry.height 			= uint8;
				entry.colorCount 		= uint8;
				if (entry.colorCount == 0)
					entry.colorCount = 256;
				uint8;//trace("reserved: " + uint8);		// reserved (ignored)
				
				entry.planes			= uint16;
				entry.bitCount			= uint16;
				entry.byteSize			= uint32;
				entry.offset			= uint32;
				
				bytearray.position 		= entry.offset;
				uint32;//trace("header size (40) : " + uint32);
				uint32;//trace("width: " + uint32);
				uint32;//trace("height: " + uint32);
				uint16;//trace("planes (1) : " + uint16);
				uint16;//trace("bitCount: " + uint16);
				uint32;//trace("compression: " + uint32);
				uint32;//trace("image size (bytes) : " + uint32);
				uint32;//trace("XpixelsPerM (0) : " + uint32);
				uint32;//trace("YpixelsPerM (0) : " + uint32);
				uint32;//trace("colors (0) : " + uint32);
				uint32;//trace("colors important (0) : " + uint32);
				
				entry.colors = new Array(entry.colorCount);
				//trace("num colors: " + entry.colorCount);
				for (var j:uint = 0; j < entry.colorCount; j++) {
					entry.colors[j] = uint32;
					//trace("color #" + j);	
					//uint8;	//ignored (alpha?!)
				}
				
				entry.bitmapData = new BitmapData(entry.width, entry.height, true, 0xFFFFFFFF);
				
					var yy:int;
					var xx:int;
					var b:uint;
				
				trace("bit count: " + entry.bitCount);
					
				switch(entry.bitCount){
					case XOR_ENCODING :
						for(yy = entry.width-1;yy>=0;--yy){
							for(xx = 0; xx < entry.width; xx+=2){
								b		= bytearray.readUnsignedByte();
								entry.bitmapData.setPixel(xx,yy,entry.colors[b >> 4]);
								entry.bitmapData.setPixel(xx+1,yy,entry.colors[b & 0x0f]);
							}
						}
						break;
						
					case XOR2_ENCODING :
						trace("xor2 (" + entry.colorCount + ") bitCount: "+ entry.bitCount);
						for (yy = entry.width - 1; yy >= 0;--yy) {
							
							//var ba:ByteArray = new ByteArray();
							//bytearray.readBytes(ba, 0, 4*entry.width);
							
							for(xx = 0; xx < entry.width; xx++){
								b		= uint8;// ba.readByte();
								entry.bitmapData.setPixel(xx, yy, entry.colors[b]);
							}
						}
						break;
						
					case RGB_ENCODING :
					case ARGB_ENCODING :
						for(yy = entry.width-1;yy>=0;--yy){
							for(xx = 0; xx < entry.width; xx++){
								//b		= bytearray.readUnsignedByte();
								entry.bitmapData.setPixel32(xx, yy, uint32);
								
							}
						}
						break;
					
				}
				
				iconEntries[i/16]		= entry;
				bytearray.position		= i+startPos; 
			}
			trace(iconEntries);
		}
		
		public function get icons():Array {
			var ret:Array = new Array(iconEntries.length);
			for(var i:uint=0;i<iconEntries.length;i++)
				ret[i] = iconEntries[i].bitmapData;
			return ret;
		}
		
		/**
		 * [internal-use]
		 * Returns a pre-defined error with the specified message.
		 *  
		 * @param message		Message
		 * @return 				ICOError object
		 * 
		 */
		protected function getError(message:String):Error {
			var err:Error = new Error(message);
			err.name = "ICOError";
			return err;
		}
		
	}
	
}

import flash.display.BitmapData;	

class IconEntry {
	
	public var width			:uint		= 0;
	public var height			:uint		= 0;
	public var colorCount		:uint		= 0;
	public var planes			:uint		= 1;
	public var bitCount			:uint		= 0;
	public var byteSize			:uint		= 0;
	public var offset			:uint		= 0;
	public var colors			:Array;
	public var bitmapData		:BitmapData;
	
	function IconEntry() {
		
	}
	
	public function toString():String {
		return '[IconEntry width="'+width+'" height="'+height+'" colorCount="'+colorCount+'" bitCount="'+bitCount+'"]';
	}
	

}